#ifndef _SE_SHADER_
#define _SE_SHADER_

#include "Core/Math.hpp"
#include "Core/Logger.h"

namespace SE
{
	class Shader
	{
	public:
        Shader() = default;
		virtual ~Shader() = default;

		virtual void bind() const = 0;
		virtual void unbind() const = 0;

		virtual void setUniformInt         (const String& name, const I32 value) = 0;
		virtual void setUniformIntArray    (const String& name, I32* values, const U32 count) = 0;
		virtual void setUniformFloat       (const String& name, const Float value) = 0;
		virtual void setUniformFloat2      (const String& name, const Vector2f& value) = 0;
		virtual void setUniformFloat3      (const String& name, const Vector3f& value) = 0;
		virtual void setUniformFloat4      (const String& name, const Vector4f& value) = 0;
		virtual void setUniformMatrix3f    (const String& name, const Matrix3f& value) = 0;
		virtual void setUniformMatrix4f    (const String& name, const Matrix4f& value) = 0;

		virtual const String& getName() const = 0;

		static Ref<Shader> Create(const String& filePath);
		static Ref<Shader> Create(const String& name, const String& vertSrc, const String& fragSrc);
	};

	class ShaderLibrary final : public SourceLibrary< String, Ref<Shader> >
	{
	public:
		ShaderLibrary() = default;
		virtual ~ShaderLibrary() = default;

		Boolean store(const String& filePath)
		{
			auto shader = Shader::Create(filePath);
			return SourceLibrary::store(shader->getName(), shader);
		}
	};
} // !namespace SE

#endif // !_SE_SHADER_